package router

import (
	"errors"
	"fmt"
	"gin/controller"
	"gin/middleware"
	"gin/queue"
	sessionsStore "gin/session"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"github.com/spf13/viper"
	etcd "github.com/teamones-open/etcd-discovery"
	register_route "github.com/teamones-open/go-register-route"
	"golang.org/x/sync/errgroup"
	"log"
	"net/http"
)

var (
	g errgroup.Group
)

func InitRouter() {
	router := gin.Default()

	// 要在路由组之前全局使用「跨域中间件」, 否则OPTIONS会返回404
	router.Use(middleware.Cors())

	// 使用 session(cookie-based)
	router.Use(sessions.Sessions("media_session", sessionsStore.Store))

	router.GET("/", controller.HealthyReturn)

	// 配置静态文件夹路径 第一个参数是api，第二个是文件夹路径
	router.StaticFS("/static", http.Dir("./static"))

	auth := router.Group("auth")
	{
		// 生成token
		auth.POST("/generate_token", controller.GenerateToken)
		// 获取token
		auth.POST("/get_token", controller.GetToken)
	}

	media := router.Group("media")
	{
		// 上传文件
		media.POST("/upload", controller.UploadMedia)
		// 获取指定文件
		media.POST("/select", controller.SelectMediaByMd5Name)
		// 删除指定文件
		media.POST("/remove", controller.RemoveMediaByMd5Name)
		// 更新媒体ext
		media.POST("/update_media_ext_by_md5_name", controller.UpdateMediaExtByMd5Name)
	}

	cos := router.Group("cos")
	{
		// 生成临时秘钥
		cos.POST("/generate_temp_secret_key", controller.GenerateTempSecretKey)
		cos.POST("/get_resource_temp_url", controller.GetResourceTempUrl)
		cos.POST("/get_bath_resource_temp_url", controller.GetBathResourceTempUrl)
	}

	port := viper.GetString("server.port")
	if port != "" {

		// 注册服务到ETCD
		etcdStatus := viper.GetString("etcd.status")
		if etcdStatus == "active" {
			etcdHost := viper.GetString("etcd.host")
			etcdPort := viper.GetString("server.port")
			etcdServerName := viper.GetString("etcd.serverName")

			g.Go(func() error {
				err := etcd.RegisterServer(etcdHost, etcdPort, etcdServerName)
				if err != nil {
					log.Fatal(err)
				}
				return err
			})
		}

		// 上报路由
		g.Go(func() error {
			err := RegisterRoutes(router)
			if err != nil {
				log.Fatal(err)
			}
			return err
		})

		// 执行队列进程
		workNum := viper.GetInt("transcode.workNumber")
		for i := 1; i <= workNum; i++ {
			runQueue(i)
		}

		// 启动http服务
		g.Go(func() error {
			err := router.Run(":" + port)
			if err != nil && err != http.ErrServerClosed {
				log.Fatal(err)
			}
			return err
		})

		if err := g.Wait(); err != nil {
			log.Fatal(err)
		}

	} else {
		portErr := errors.New("The port number does not exist.")
		log.Fatal(portErr)
	}
}

// 运行amqp队列得消费者
func runQueue(workNum int) {
	g.Go(func() error {
		err := runQueueWorker(workNum)
		if err != nil {
			log.Fatal(err)
		}
		return err
	})
}

// 启动worker
func runQueueWorker(workNum int) (err error) {
	taskWorker := queue.NewAsyncTaskWorker(fmt.Sprintf("%s_%d", "worker", workNum), 1)
	err = taskWorker.Launch()
	return err
}

// 路由上报注册
func RegisterRoutes(router *gin.Engine) (err error) {
	Routes := router.Routes()
	url := viper.GetString("rotueServer.url")
	serverName := viper.GetString("etcd.serverName")
	err = register_route.Register(Routes, url, serverName)
	return err
}
